namespace CollabApp.Domain.ValueObjects;

/// <summary>
/// 游戏分数值对象 - 表示玩家在圈地游戏中的得分
/// 包含领地面积、击杀数、生存时间等多维度评分
/// </summary>
public sealed class GameScore : IEquatable<GameScore>, IComparable<GameScore>
{
    /// <summary>
    /// 基础分数 - 主要来自领地面积
    /// </summary>
    public float BaseScore { get; }
    
    /// <summary>
    /// 领地面积（像素）
    /// </summary>
    public float TerritoryArea { get; }
    
    /// <summary>
    /// 领地面积百分比（占总地图面积的比例）
    /// </summary>
    public float AreaPercentage { get; }
    
    /// <summary>
    /// 击杀数 - 成功截断其他玩家的次数
    /// </summary>
    public int KillCount { get; }
    
    /// <summary>
    /// 死亡数 - 被其他玩家截断的次数
    /// </summary>
    public int DeathCount { get; }
    
    /// <summary>
    /// 生存时间（秒）
    /// </summary>
    public int SurvivalTime { get; }
    
    /// <summary>
    /// 最大连续圈地次数
    /// </summary>
    public int MaxComboCount { get; }
    
    /// <summary>
    /// 道具使用次数
    /// </summary>
    public int ItemUsageCount { get; }
    
    /// <summary>
    /// 总分数 - 综合所有因素的最终得分
    /// </summary>
    public float TotalScore { get; }
    
    /// <summary>
    /// 排名 - 在本局游戏中的排名
    /// </summary>
    public int Rank { get; }

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="territoryArea">领地面积</param>
    /// <param name="areaPercentage">面积百分比</param>
    /// <param name="killCount">击杀数</param>
    /// <param name="deathCount">死亡数</param>
    /// <param name="survivalTime">生存时间</param>
    /// <param name="maxComboCount">最大连击</param>
    /// <param name="itemUsageCount">道具使用次数</param>
    /// <param name="rank">排名</param>
    public GameScore(
        float territoryArea = 0f,
        float areaPercentage = 0f,
        int killCount = 0,
        int deathCount = 0,
        int survivalTime = 0,
        int maxComboCount = 0,
        int itemUsageCount = 0,
        int rank = 1)
    {
        TerritoryArea = Math.Max(0, territoryArea);
        AreaPercentage = Math.Max(0, Math.Min(100, areaPercentage));
        KillCount = Math.Max(0, killCount);
        DeathCount = Math.Max(0, deathCount);
        SurvivalTime = Math.Max(0, survivalTime);
        MaxComboCount = Math.Max(0, maxComboCount);
        ItemUsageCount = Math.Max(0, itemUsageCount);
        Rank = Math.Max(1, rank);

        // 计算基础分数（主要基于领地面积）
        BaseScore = TerritoryArea;

        // 计算总分数（多维度评分系统）
        TotalScore = CalculateTotalScore();
    }

    /// <summary>
    /// 零分数 - 表示没有任何得分
    /// </summary>
    public static GameScore Zero => new();

    /// <summary>
    /// 创建基于面积的简单分数
    /// </summary>
    /// <param name="area">领地面积</param>
    /// <param name="percentage">面积百分比</param>
    /// <param name="rank">排名</param>
    /// <returns>游戏分数对象</returns>
    public static GameScore FromArea(float area, float percentage, int rank = 1)
    {
        return new GameScore(territoryArea: area, areaPercentage: percentage, rank: rank);
    }

    /// <summary>
    /// 创建完整的分数对象
    /// </summary>
    /// <param name="territoryArea">领地面积</param>
    /// <param name="areaPercentage">面积百分比</param>
    /// <param name="killCount">击杀数</param>
    /// <param name="deathCount">死亡数</param>
    /// <param name="survivalTime">生存时间</param>
    /// <param name="maxComboCount">最大连击</param>
    /// <param name="itemUsageCount">道具使用次数</param>
    /// <param name="rank">排名</param>
    /// <returns>完整的游戏分数对象</returns>
    public static GameScore Create(
        float territoryArea,
        float areaPercentage,
        int killCount,
        int deathCount,
        int survivalTime,
        int maxComboCount,
        int itemUsageCount,
        int rank)
    {
        return new GameScore(
            territoryArea, areaPercentage, killCount, deathCount,
            survivalTime, maxComboCount, itemUsageCount, rank);
    }

    /// <summary>
    /// 计算总分数 - 多维度评分算法
    /// </summary>
    private float CalculateTotalScore()
    {
        var score = 0f;

        // 1. 领地面积分数（权重70%）- 主要评分标准
        score += TerritoryArea * 0.7f;

        // 2. 击杀奖励分数（权重15%）
        score += KillCount * 100 * 0.15f;

        // 3. 生存时间奖励（权重10%）
        score += SurvivalTime * 0.5f * 0.10f;

        // 4. 连击奖励（权重3%）
        score += MaxComboCount * 50 * 0.03f;

        // 5. 道具使用奖励（权重2%）
        score += ItemUsageCount * 10 * 0.02f;

        // 6. 死亡惩罚
        score -= DeathCount * 50;

        // 7. K/D比率奖励
        if (DeathCount == 0 && KillCount > 0)
        {
            score += 100; // 零死亡奖励
        }
        else if (DeathCount > 0)
        {
            var kdRatio = (float)KillCount / DeathCount;
            if (kdRatio > 1)
            {
                score += kdRatio * 25; // K/D比率奖励
            }
        }

        return Math.Max(0, score);
    }

    /// <summary>
    /// 获取表现等级
    /// </summary>
    /// <returns>表现等级描述</returns>
    public string GetPerformanceGrade()
    {
        return AreaPercentage switch
        {
            >= 50f => "S", // 统治级
            >= 30f => "A", // 优秀
            >= 20f => "B", // 良好
            >= 10f => "C", // 一般
            >= 5f => "D",  // 需要努力
            _ => "F"       // 惨败
        };
    }

    /// <summary>
    /// 获取击杀效率
    /// </summary>
    /// <returns>击杀死亡比</returns>
    public float GetKillDeathRatio()
    {
        return DeathCount == 0 
            ? (KillCount > 0 ? float.PositiveInfinity : 0f)
            : (float)KillCount / DeathCount;
    }

    /// <summary>
    /// 检查是否达成特殊成就
    /// </summary>
    /// <returns>成就列表</returns>
    public List<string> GetAchievements()
    {
        var achievements = new List<string>();

        if (AreaPercentage >= 70f)
            achievements.Add("地图霸主"); // 占领70%以上领地
        
        if (AreaPercentage >= 50f)
            achievements.Add("统治者"); // 占领50%以上领地
        
        if (KillCount >= 5)
            achievements.Add("屠戮者"); // 击杀5人以上
        
        if (DeathCount == 0 && SurvivalTime > 120)
            achievements.Add("不死传说"); // 零死亡且存活2分钟以上
        
        if (MaxComboCount >= 3)
            achievements.Add("连击大师"); // 连续圈地3次以上
        
        if (GetKillDeathRatio() >= 3f && KillCount > 0)
            achievements.Add("精英狙击"); // K/D比率3:1以上
        
        if (AreaPercentage >= 30f && ItemUsageCount == 0)
            achievements.Add("纯技术流"); // 不使用道具获得30%面积

        return achievements;
    }

    /// <summary>
    /// 更新排名
    /// </summary>
    /// <param name="newRank">新排名</param>
    /// <returns>更新后的分数对象</returns>
    public GameScore WithRank(int newRank)
    {
        return new GameScore(
            TerritoryArea, AreaPercentage, KillCount, DeathCount,
            SurvivalTime, MaxComboCount, ItemUsageCount, newRank);
    }

    /// <summary>
    /// 增加击杀数
    /// </summary>
    /// <param name="kills">增加的击杀数</param>
    /// <returns>更新后的分数对象</returns>
    public GameScore AddKills(int kills)
    {
        return new GameScore(
            TerritoryArea, AreaPercentage, KillCount + kills, DeathCount,
            SurvivalTime, MaxComboCount, ItemUsageCount, Rank);
    }

    /// <summary>
    /// 增加死亡数
    /// </summary>
    /// <param name="deaths">增加的死亡数</param>
    /// <returns>更新后的分数对象</returns>
    public GameScore AddDeaths(int deaths)
    {
        return new GameScore(
            TerritoryArea, AreaPercentage, KillCount, DeathCount + deaths,
            SurvivalTime, MaxComboCount, ItemUsageCount, Rank);
    }

    /// <summary>
    /// 更新领地面积
    /// </summary>
    /// <param name="area">新的领地面积</param>
    /// <param name="percentage">新的面积百分比</param>
    /// <returns>更新后的分数对象</returns>
    public GameScore UpdateArea(float area, float percentage)
    {
        return new GameScore(
            area, percentage, KillCount, DeathCount,
            SurvivalTime, MaxComboCount, ItemUsageCount, Rank);
    }

    // IEquatable实现
    public bool Equals(GameScore? other)
    {
        if (other is null) return false;
        if (ReferenceEquals(this, other)) return true;
        
        return Math.Abs(TotalScore - other.TotalScore) < 0.001f;
    }

    public override bool Equals(object? obj) => Equals(obj as GameScore);

    public override int GetHashCode() => TotalScore.GetHashCode();

    // IComparable实现 - 按总分数降序排序
    public int CompareTo(GameScore? other)
    {
        if (other is null) return 1;
        
        var scoreComparison = other.TotalScore.CompareTo(TotalScore); // 降序
        if (scoreComparison != 0) return scoreComparison;
        
        // 分数相同时按面积百分比排序
        var areaComparison = other.AreaPercentage.CompareTo(AreaPercentage); // 降序
        if (areaComparison != 0) return areaComparison;
        
        // 面积相同时按击杀数排序
        return other.KillCount.CompareTo(KillCount); // 降序
    }

    public override string ToString()
    {
        return $"分数: {TotalScore:F0} (面积: {AreaPercentage:F1}%, 击杀: {KillCount}, 排名: {Rank})";
    }

    // 运算符重载
    public static bool operator ==(GameScore? left, GameScore? right)
    {
        return left?.Equals(right) ?? right is null;
    }

    public static bool operator !=(GameScore? left, GameScore? right)
    {
        return !(left == right);
    }

    public static bool operator <(GameScore left, GameScore right)
    {
        return left is null ? right is not null : left.CompareTo(right) < 0;
    }

    public static bool operator <=(GameScore left, GameScore right)
    {
        return left is null || left.CompareTo(right) <= 0;
    }

    public static bool operator >(GameScore left, GameScore right)
    {
        return left is not null && left.CompareTo(right) > 0;
    }

    public static bool operator >=(GameScore left, GameScore right)
    {
        return left is null ? right is null : left.CompareTo(right) >= 0;
    }
}
